package com.hyt.it.ogt.pj.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.enums.DelFlagEnum;
import com.hyt.core.util.DateUtils;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.common.utils.ExecutorPoolUtil;
import com.hyt.it.ogt.pj.asynchronous.Ayns2Cj;
import com.hyt.it.ogt.pj.asynchronous.BatchUpdateStudentStatusKw;
import com.hyt.it.ogt.pj.common.Constants;
import com.hyt.it.ogt.pj.common.MarkException;
import com.hyt.it.ogt.pj.common.ResponseCode;
import com.hyt.it.ogt.pj.enums.AutoFlagEnums;
import com.hyt.it.ogt.pj.enums.CommonEnums;
import com.hyt.it.ogt.pj.enums.MarkTypeEnums;
import com.hyt.it.ogt.pj.enums.MarkmodelEnums;
import com.hyt.it.ogt.pj.enums.PaperItemTypeCode;
import com.hyt.it.ogt.pj.enums.RejudgeEnums;
import com.hyt.it.ogt.pj.enums.SubjectScoreStageEnums;
import com.hyt.it.ogt.pj.feign.KwClient;
import com.hyt.it.ogt.pj.mapper.ItemScoreMapper;
import com.hyt.it.ogt.pj.mapper.PaperItemMapper;
import com.hyt.it.ogt.pj.mapper.PaperMapper;
import com.hyt.it.ogt.pj.mapper.PieceScoreMapper;
import com.hyt.it.ogt.pj.mapper.ProjectMapper;
import com.hyt.it.ogt.pj.mapper.ProjectSettingMapper;
import com.hyt.it.ogt.pj.mapper.SubjectScoreMapper;
import com.hyt.it.ogt.pj.mapper.TaskMapper;
import com.hyt.it.ogt.pj.mapper.TaskTimeMapper;
import com.hyt.it.ogt.pj.model.entity.Config;
import com.hyt.it.ogt.pj.model.entity.ItemScore;
import com.hyt.it.ogt.pj.model.entity.Log;
import com.hyt.it.ogt.pj.model.entity.Paper;
import com.hyt.it.ogt.pj.model.entity.PaperItem;
import com.hyt.it.ogt.pj.model.entity.Piece;
import com.hyt.it.ogt.pj.model.entity.PieceScore;
import com.hyt.it.ogt.pj.model.entity.PieceScoreLog;
import com.hyt.it.ogt.pj.model.entity.Project;
import com.hyt.it.ogt.pj.model.entity.ProjectSetting;
import com.hyt.it.ogt.pj.model.entity.Student;
import com.hyt.it.ogt.pj.model.entity.Subject;
import com.hyt.it.ogt.pj.model.entity.SubjectScore;
import com.hyt.it.ogt.pj.model.entity.Task;
import com.hyt.it.ogt.pj.model.entity.TaskTime;
import com.hyt.it.ogt.pj.model.entity.TeacherTaskInfo;
import com.hyt.it.ogt.pj.model.vo.CandidateSubjectiveScoreVO;
import com.hyt.it.ogt.pj.model.vo.ItemScoreVo;
import com.hyt.it.ogt.pj.model.vo.ItemType;
import com.hyt.it.ogt.pj.model.vo.MarkBatchVo;
import com.hyt.it.ogt.pj.model.vo.MarkData;
import com.hyt.it.ogt.pj.model.vo.MarkDataVo;
import com.hyt.it.ogt.pj.model.vo.MarkStatusVo;
import com.hyt.it.ogt.pj.model.vo.MarkSubjectVo;
import com.hyt.it.ogt.pj.model.vo.OptionItemVo;
import com.hyt.it.ogt.pj.model.vo.PaperItemVo;
import com.hyt.it.ogt.pj.model.vo.TaskVo;
import com.hyt.it.ogt.pj.model.vo.UpdateCandidateJudgeStateVO;
import com.hyt.it.ogt.pj.service.IConfigService;
import com.hyt.it.ogt.pj.service.IItemScoreService;
import com.hyt.it.ogt.pj.service.ILogService;
import com.hyt.it.ogt.pj.service.IPaperItemService;
import com.hyt.it.ogt.pj.service.IPaperService;
import com.hyt.it.ogt.pj.service.IPieceScoreLogService;
import com.hyt.it.ogt.pj.service.IPieceScoreService;
import com.hyt.it.ogt.pj.service.IPieceService;
import com.hyt.it.ogt.pj.service.IProjectService;
import com.hyt.it.ogt.pj.service.IProjectSettingService;
import com.hyt.it.ogt.pj.service.IStudentService;
import com.hyt.it.ogt.pj.service.ISubjectScoreService;
import com.hyt.it.ogt.pj.service.ISubjectService;
import com.hyt.it.ogt.pj.service.ISynDataService;
import com.hyt.it.ogt.pj.service.ITaskService;
import com.hyt.it.ogt.pj.service.ITeacherTaskInfoService;
import com.hyt.it.ogt.ykcj.service.exchange.IApiLogService;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 评卷任务表 服务实现类
 * </p>
 *
 * @author qiaozj
 * @since 2020-07-09
 */
@Service
@Slf4j
public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implements ITaskService {

    @Resource
    IApiLogService iApiLogService;
    
    @Resource
    private IProjectService projectService;

    @Resource
    private IPieceService pieceService;

    @Resource
    private TaskMapper taskMapper;

    @Resource
    private IPaperService paperService;

    @Resource
    private IPaperItemService paperItemService;

    @Resource
    private IPieceScoreService pieceScoreService;

    @Resource
    private PieceScoreMapper pieceScoreMapper;

    @Resource
    private IItemScoreService itemScoreService;

    @Resource
    private ILogService logService;

    @Resource
    private ITeacherTaskInfoService teacherTaskInfoService;

    @Resource
    private IConfigService configService;

    @Resource
    private ISubjectService subjectService;

    @Resource
    private ISubjectScoreService subjectScoreService;

    @Resource
    private IStudentService studentService;

    @Resource
    private KwClient kwClient;

    @Resource
    private ProjectSettingMapper projectSettingMapper;

    @Resource
    private PaperItemMapper paperItemMapper;

    @Resource
    private TaskTimeMapper taskTimeMapper;

    @Resource
    private ProjectMapper projectMapper;

    @Resource
    private ISynDataService synDataService;

    @Resource
    private SubjectScoreMapper subjectScoreMapper;

    @Resource
    private IPieceScoreLogService pieceScoreLogService;

    @Resource
    private BatchUpdateStudentStatusKw batchUpdateStudentStatusKw;

    @Resource
    private PaperMapper paperMapper;

    @Resource
    private ItemScoreMapper itemScoreMapper;

    @Resource
    private ITaskService taskService;

    @Resource
    private IProjectSettingService projectSettingService;

    @Override
    public List<MarkData> findTask(String projectId, String subjectId, String pieceCode, String userId) {
        List<MarkData> markDataList = null;
        // 获取评卷科目
        if (subjectId == null) {
            Subject subject = subjectService.getMarkSubject(projectId);
            if (subject != null) {
                subjectId = subject.getSubjectId();
            } else {
                return null;
            }
        }
        TeacherTaskInfo teacherTaskInfo = teacherTaskInfoService.getByUserId(projectId, subjectId, userId);
        if (teacherTaskInfo == null) {
            projectService.createTeacherTaskInfo(projectId, subjectId, userId);
        }
        if (pieceCode != null) {
            markDataList = findTaskByPiece(projectId, subjectId, pieceCode, userId);
        } else {
            markDataList = findTaskBySubject(projectId, subjectId, pieceCode, userId);
        }
        return markDataList;
    }

    @Override
    public List<MarkData> findTaskBySubject(String projectId, String subjectId, String pieceCode, String userId) {
        //通过当没有pieceCode传入时，则需要先获取到该教师的pieceCode然后再通过PieceCode获取评卷任务
        Piece piece = pieceService.getTeacherPiece(projectId, subjectId, userId);
        List<MarkData> markDataList = null;
        if (piece != null) {
            markDataList = findTaskByPiece(projectId, subjectId, piece.getId(), userId);
        }
        return markDataList;
    }

    @Override
    public List<MarkData> findTaskByPiece(String projectId, String subjectId, String pieceCode, String userId) {
        //查询评卷任务
        List<Task> taskList = getMarkTaskList(projectId, subjectId, userId);
        if (taskList == null) {
            return Collections.emptyList();
        }
        //生成前端评卷数据
        List<MarkData> markDataList = new ArrayList<>(Arrays.asList(new MarkData[taskList.size()]));
        for (Task task : taskList) {
            Piece piece = pieceService.getById(task.getPieceId());
            MarkData markData = new MarkData();
            markData.setProjectId(projectId);
            markData.setSubjectId(subjectId);
            markData.setPaperId(piece.getPaperId());
            markData.setPaperName(piece.getPieceName());
            if (task.getStatus() == 1) {
                markData.setTask(task);
                String encodeId = task.getEncodeId();
                markData.setEncodeId(task.getEncodeId());
                markData.setPieceCode(pieceCode);
                markData.setPieceId(piece.getId());
                String paperId = markData.getPaperId();
                List<ItemType> itemTypes = paperService.selectItemTypes(paperId, subjectId, piece.getId(), encodeId);
                markData.setItemTypes(itemTypes);
                List<PaperItemVo> children = paperItemService.selectMarkItem(projectId, subjectId, paperId, encodeId, null);
                markData.setChildren(children);
                markData.setFinish(false);
            } else {
                //已评卷完成
                markData.setFinish(true);
            }
            markDataList.set(piece.getSort() - 1, markData);
        }
        return markDataList;
    }

    private List<Task> getMarkTaskList(String projectId, String subjectId, String userId) {
        //查询正在评卷的任务
        Task markingTask = this.lambdaQuery()
                .eq(Task::getProjectId, projectId)
                .eq(Task::getSubjectId, subjectId)
                .eq(Task::getLoadby, userId)
                .eq(Task::getStatus, 1)
                .last("LIMIT 1")
                .one();
        if (markingTask == null) {
            //没有当前用户正在评卷的任务，找一个没评卷的考生
            markingTask = this.lambdaQuery()
                    .eq(Task::getProjectId, projectId)
                    .eq(Task::getSubjectId, subjectId)
                    .eq(Task::getStatus, 0)
                    .last("LIMIT 1")
                    .one();
            if (markingTask == null) {
                //没有未评卷的考生了
                return Collections.emptyList();
            } else {
                //更新评卷任务状态为被获取
                this.lambdaUpdate()
                        .eq(Task::getProjectId, projectId)
                        .eq(Task::getSubjectId, subjectId)
                        .eq(Task::getEncodeId, markingTask.getEncodeId())
                        .eq(Task::getStatus, 0)
                        .set(Task::getStatus, 1)
                        .set(Task::getLoadby, userId)
                        .update();
            }
        }
        //查询考生所有评卷任务，支持试卷包评卷
        return this.lambdaQuery()
                .eq(Task::getProjectId, projectId)
                .eq(Task::getSubjectId, subjectId)
                .eq(Task::getEncodeId, markingTask.getEncodeId())
                .list();
    }

    @Override
    public List<MarkData> findStudentTask(String projectId, String subjectId, String admissionNum, String userId) {
        Integer count = studentService.lambdaQuery()
                .eq(Student::getProjectId, projectId)
                .eq(Student::getAdmissionNum, admissionNum)
                .count();
        if (count == null || count == 0) {
            return Collections.emptyList();
        }
        TeacherTaskInfo teacherTaskInfo = teacherTaskInfoService.getByUserId(projectId, subjectId, userId);
        if (teacherTaskInfo == null) {
            projectService.createTeacherTaskInfo(projectId, subjectId, userId);
        }
        List<Task> taskList = getStudentMarkTaskList(projectId, subjectId, admissionNum, userId);
        if (taskList == null) {
            return Collections.emptyList();
        }
        //生成前端评卷数据
        List<MarkData> markDataList = new ArrayList<>(Arrays.asList(new MarkData[taskList.size()]));
        for (Task task : taskList) {
            Piece piece = pieceService.getById(task.getPieceId());
            MarkData markData = new MarkData();
            markData.setProjectId(projectId);
            markData.setSubjectId(subjectId);
            markData.setPaperId(piece.getPaperId());
            markData.setPaperName(piece.getPieceName());
            if (task.getStatus() == 1) {
                markData.setTask(task);
                String encodeId = task.getEncodeId();
                markData.setEncodeId(task.getEncodeId());
                markData.setPieceCode(piece.getParentId());
                markData.setPieceId(piece.getId());
                String paperId = markData.getPaperId();
                List<ItemType> itemTypes = paperService.selectItemTypes(paperId, subjectId, piece.getId(), encodeId);
                markData.setItemTypes(itemTypes);
                List<PaperItemVo> children = paperItemService.selectMarkItem(projectId, subjectId, paperId, encodeId, null);
                markData.setChildren(children);
                markData.setFinish(false);
            } else {
                //已评卷完成
                markData.setFinish(true);
            }
            markDataList.set(piece.getSort() - 1, markData);
        }
        markDataList.removeAll(Collections.singleton(null));
        return markDataList;
    }

    private List<Task> getStudentMarkTaskList(String projectId, String subjectId, String admissionNum, String userId) {
        //更新评卷任务状态为被获取
        this.lambdaUpdate()
                .eq(Task::getProjectId, projectId)
                .eq(Task::getSubjectId, subjectId)
                .eq(Task::getEncodeId, admissionNum)
                .eq(Task::getStatus, 0)
                .isNull(Task::getLoadby)
                .set(Task::getStatus, 1)
                .set(Task::getLoadby, userId)
                .update();
        //查询考生所有评卷任务，支持试卷包评卷
        return this.lambdaQuery()
                .eq(Task::getProjectId, projectId)
                .eq(Task::getSubjectId, subjectId)
                .eq(Task::getEncodeId, admissionNum)
                .eq(Task::getLoadby, userId)
                .list();
    }

    public boolean isFinishMark(String projectId, String subjectId, String pieceCode) {
        boolean flag = false;
        List<Task> unMarkTasks = taskMapper.selectUnMarkTask(projectId, subjectId, pieceCode);
        if (unMarkTasks == null || unMarkTasks.size() == 0) {
            flag = true;
        }
        return flag;
    }

    @Override
    // @GlobalTransactional(rollbackFor = Exception.class)
    public Integer submitTask(MarkData markData, String userId) {
        //1.itemScore, log,pieceScore, subjectScore, teacherTaskInfo totalScore
        String projectId = markData.getProjectId();
        String subjectId = markData.getSubjectId();
        String pieceCode = markData.getPieceCode();
        String pieceId = markData.getPieceId();
        Task task = markData.getTask();
        task.setLoadby(userId);
        task.setStatus(2);
        task.setMarkStatus(2);
        taskMapper.updateStatus(task);
        String taskId = task.getId();
        String encodeId = task.getEncodeId();
        List<PaperItemVo> paperItemVos = markData.getChildren();
        List<ItemScore> itemScores = new ArrayList<>();
        StringBuffer subScore = new StringBuffer();
        if (markData.getMarkType() == 1) {
            itemScoreService.deleteStudentScoreByTaskIdAndEncodeId(taskId, encodeId);
            pieceScoreService.deleteStuScoreBySubjectIdAndPieceIdAndEncodeId(subjectId, pieceId, encodeId);
        }
        getItemScore(markData, paperItemVos, itemScores, userId, subScore);
        itemScoreService.saveBatch(itemScores);
        //主观题分、客观题分、总分
        BigDecimal pieceSubjectiveScore = new BigDecimal(0);
        BigDecimal pieceObjectiveScore = new BigDecimal(0);
        BigDecimal totalScore = new BigDecimal(0);
        List<ItemType> itemTypes = markData.getItemTypes();
        for (ItemType itemType : itemTypes) {
            if (itemType.getItemViewPoint()) {
                //客观题
                pieceObjectiveScore = itemType.getTypeScore();
            } else {
                //主观题
                pieceSubjectiveScore = itemType.getTypeScore();
                totalScore = itemType.getTotalScore();
            }
        }
        //查询评卷块分数
        PieceScore pieceScore = pieceScoreService.lambdaQuery()
                .eq(PieceScore::getSubjectId, subjectId)
                .eq(PieceScore::getPieceId, pieceId)
                .eq(PieceScore::getTaskId, taskId)
                .eq(PieceScore::getEncodeId, encodeId)
                .eq(PieceScore::getDelFlag, false)
                .one();
        if (pieceScore == null) {
            pieceScore = new PieceScore();
            pieceScore.setSubjectId(subjectId);
            pieceScore.setPieceId(pieceId);
            pieceScore.setTaskId(taskId);
            pieceScore.setEncodeId(encodeId);
            pieceScore.setUserId(userId);
            pieceScore.setObjectiveScore(pieceObjectiveScore);
            pieceScore.setSubjectiveScore(pieceSubjectiveScore);
            pieceScore.setScore(totalScore);
            pieceScore.setStage(Constants.MARK_STAGE);
            pieceScoreService.save(pieceScore);
        } else {
            pieceScore.setObjectiveScore(pieceObjectiveScore);
            pieceScore.setSubjectiveScore(pieceSubjectiveScore);
            pieceScore.setScore(totalScore);
            pieceScoreService.updateById(pieceScore);
        }
        //日志
        Log submitLog = new Log();
        submitLog.setProjectId(projectId);
        submitLog.setEncodeId(encodeId);
        submitLog.setScore(pieceScore.getScore());
        submitLog.setStage(Constants.MARK_STAGE);
        submitLog.setSubScore(subScore.toString());
        submitLog.setTaskId(taskId);
        submitLog.setUserId(userId);
        logService.save(submitLog);
        //科目评卷块分数
        PieceScore subjectPieceScore = pieceScore;
        //更新科目分数
        Config config = configService.selectByLabel(projectId, Constants.MARK_MODEL);
        if (config != null && "A".equals(config.getValue())) {
            SubjectScore subjectScore = subjectScoreService.getStudentSubjectScore(projectId, subjectId, encodeId);
            boolean flag = true;
            if (subjectScore == null) {
                flag = false;
                subjectScore = new SubjectScore();
                subjectScore.setProjectId(projectId);
                subjectScore.setSubjectId(subjectId);
                subjectScore.setAdmissionNum(encodeId);
                subjectScore.setEncodeId(encodeId);
                subjectScore.setObjectiveScore(new BigDecimal(0));
            }
            //查询项目分数
            subjectPieceScore = pieceScoreService.selectPieceScore(subjectId, null, encodeId);
            subjectScore.setObjectiveScore(subjectPieceScore.getObjectiveScore());
            subjectScore.setSubjectiveScore(subjectPieceScore.getSubjectiveScore());
            subjectScore.setTotalScore(subjectPieceScore.getScore());
            if (flag) {
                subjectScoreService.updateById(subjectScore);
            } else {
                subjectScoreService.save(subjectScore);
            }
        }
        // 查询考生已评卷任务数
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Task::getProjectId, projectId)
                .eq(Task::getEncodeId, encodeId)
                .eq(Task::getMarkStatus, CommonEnums.MARK_STATUS_2.getCode());
        // 改考生全部任务数
        QueryWrapper<Task> queryWrapperAll = new QueryWrapper<>();
        queryWrapperAll.lambda()
                .eq(Task::getProjectId, projectId)
                .eq(Task::getEncodeId, encodeId);
        int count = this.count(queryWrapper);
        int countAll = this.count(queryWrapperAll);
        log.info("### 已评卷数量和全部评卷量:{},{}", count, countAll);
        if (count == countAll) {
            //更新评卷教师任务信息
            TeacherTaskInfo teacherTaskInfo = teacherTaskInfoService.selectMarkInfo(projectId, subjectId, pieceCode, userId);
            BigDecimal pieceRealScore = subjectPieceScore.getScore();
            BigDecimal highScore = teacherTaskInfo.getHighScore();
            if (highScore.compareTo(pieceRealScore) < 0) {
                teacherTaskInfo.setHighScore(pieceRealScore);
            }
            BigDecimal lowScore = teacherTaskInfo.getLowScore();
            if (lowScore.compareTo(pieceRealScore) > 0) {
                teacherTaskInfo.setLowScore(pieceRealScore);
            }
            teacherTaskInfo.setSumScore(teacherTaskInfo.getSumScore().add(pieceRealScore));
            teacherTaskInfo.setTaskNum(teacherTaskInfo.getTaskNum() + 1);
            teacherTaskInfo.setUseTime(teacherTaskInfo.getUseTime() + markData.getUserTime());
            teacherTaskInfoService.updateById(teacherTaskInfo);
            //更新考生评卷状态
            UpdateCandidateJudgeStateVO updateCandidateJudgeStateVO = new UpdateCandidateJudgeStateVO();
            updateCandidateJudgeStateVO.setProjectId(projectId);
            updateCandidateJudgeStateVO.setAdmissionNum(encodeId);
            updateCandidateJudgeStateVO.setSubjectiveScore(subjectPieceScore.getSubjectiveScore().toString());
            // 返回小题得分
            List<CandidateSubjectiveScoreVO> candidateSubjectiveScoreVOS = getCandidateSubjectiveScoreVOs(projectId, encodeId);
            updateCandidateJudgeStateVO.setCandidateSubjectiveScoreList(candidateSubjectiveScoreVOS);
            log.info("updateCandidateJudgeState params:[{}]", JSONObject.toJSONString(candidateSubjectiveScoreVOS));
            kwClient.updateCandidateJudgeState(updateCandidateJudgeStateVO);
            log.info("updateCandidateJudgeState result:[{}]", JSONObject.toJSONString(candidateSubjectiveScoreVOS));
        }
        return ResponseCode.SUCCESS;
    }

    @Override
    public List<Task> getStudentSubjectTask(String projectId, String subjectId, String admissionNum) {
        return taskMapper.getStudentSubjectTask(projectId, subjectId, admissionNum);
    }

    @Override
    public MarkDataVo getStudentPaper(String pieceScoreId, String admissionNo, String userId, Integer finish, Integer mobileMark) {
        MarkDataVo markDataVo = new MarkDataVo();
        // 获取task
        Task task = taskMapper.selectTaskByPieceScore(pieceScoreId, userId);
        // 获取project
        Project project = projectMapper.selectById(task.getProjectId());
        // 获取题目数据
        List<PaperItemVo> paperItemVoList = paperItemService.selectBlockList(task.getId(), task.getProjectId(), task.getSubjectId(), task.getPaperId(), task.getEncodeId(), userId);
        // 获取projectSetting来判断这个评卷是否可以重现编辑
        ProjectSetting projectSetting = projectSettingMapper.getProjectSettingByPieceScoreId(pieceScoreId);
        // 获取试卷数据
        PieceScore pieceScore = null;
        if (CommonEnums.MOBILE_MARK_0.getCode().equals(markDataVo.getMobileMark())) {
            pieceScore = pieceScoreMapper.getPieceScoreByAdmissioIdAndUserId(task.getProjectId(), task.getSubjectId(), userId, task.getEncodeId());
        } else {
            pieceScore = pieceScoreMapper.getPieceScoreByAdmissioId(task.getProjectId(), task.getSubjectId(), userId, task.getEncodeId(), finish);
        }
        // 如果是允许回评，则加载已经完成的评卷数据
        if (null == pieceScore && StringUtils.isNoneBlank(projectSetting.getRejudge()) && RejudgeEnums.MARK_TYPE_ALLOW_REVIEW.getCode().equals(projectSetting.getRejudge())) {
            pieceScore = pieceScoreMapper.getPieceScoreByAdmissioId(task.getProjectId(), task.getSubjectId(), userId, task.getEncodeId(), CommonEnums.PIECCE_SCORE_FINSH_1.getCode());
        }
        if (null == pieceScore) {
            return null;
        }
        // 评卷时间判断
        TaskTime taskTime = taskTimeMapper.getTaskTimeByBatchIdAndPlaceIdAndRoomId(task.getProjectId(), task.getSubjectId(), task.getBatchId(), task.getPlaceId(), task.getRoomId());
        // 存在设置的时间为空的情况
        if (taskTime == null || (taskTime.getEndTime() == null && taskTime.getStartTime() == null)) {
            // 判断是否在评卷时间内，如果是，那么设置开始评卷的时间
            // 只要第一次查看了这个试卷，那么就设置为老师开始评卷的时间
            updatePieceScore(pieceScore);
        } else if (taskTime.getEndTime() == null && taskTime.getStartTime() != null && taskTime.getStartTime().compareTo(new Date()) < 0) {
            // 判断是否在评卷时间内，如果是，那么设置开始评卷的时间
            // 只要第一次查看了这个试卷，那么就设置为老师开始评卷的时间
            updatePieceScore(pieceScore);
        } else if (taskTime.getStartTime() == null && taskTime.getEndTime() != null && taskTime.getEndTime().compareTo(new Date()) > 0) {
            // 判断是否在评卷时间内，如果是，那么设置开始评卷的时间
            // 只要第一次查看了这个试卷，那么就设置为老师开始评卷的时间
            updatePieceScore(pieceScore);
        } else {
            if (taskTime.getEndTime().compareTo(new Date()) > 0 && taskTime.getStartTime().compareTo(new Date()) < 0) {
                // 判断是否在评卷时间内，如果是，那么设置开始评卷的时间
                // 只要第一次查看了这个试卷，那么就设置为老师开始评卷的时间
                updatePieceScore(pieceScore);
            }
        }
        // 根据finish来设置没有在评卷时候设置itemScore的数据
        for (PaperItemVo paperItemVo : paperItemVoList) {
            for (PaperItemVo child : paperItemVo.getChildren()) {
                if (CommonEnums.PIECCE_SCORE_FINSH_1.getCode().equals(task.getFinish()) && child.getObtainScore() == null) {
                    child.setObtainScore(BigDecimal.ZERO);
                }
            }
        }

        if (null != taskTime) {
            if (null != taskTime.getEndTime() && taskTime.getEndTime().compareTo(new Date()) < 0) {
                markDataVo.setGradingStatus(CommonEnums.GRADING_STATUS_2.getCode().toString());
            } else if (null != taskTime.getStartTime() && null != taskTime.getEndTime() && taskTime.getStartTime().compareTo(new Date()) <= 0 && taskTime.getEndTime().compareTo(new Date()) > 0) {
                markDataVo.setGradingStatus(CommonEnums.GRADING_STATUS_1.getCode().toString());
            } else if (taskTime.getEndTime() == null && taskTime.getStartTime() != null && taskTime.getStartTime().compareTo(new Date()) < 0) {
                markDataVo.setGradingStatus(CommonEnums.GRADING_STATUS_1.getCode().toString());
            } else if (taskTime.getStartTime() == null && taskTime.getEndTime() != null && taskTime.getEndTime().compareTo(new Date()) > 0) {
                markDataVo.setGradingStatus(CommonEnums.GRADING_STATUS_1.getCode().toString());
            } else {
                markDataVo.setGradingStatus(CommonEnums.GRADING_STATUS_0.getCode().toString());
            }
        }

        // 设置task状态
        if (CommonEnums.TASK_MARK_STATUS_0.getCode().equals(task.getMarkStatus()) || null == task.getMarkStatus()) {
            task.setMarkStatus(CommonEnums.TASK_MARK_STATUS_1.getCode());
            taskService.updateById(task);
        }

        // 获取考生的信息数据
        markDataVo.setAdmissionNum(admissionNo);
        markDataVo.setTaskId(task.getId());
        markDataVo.setPieceScoreId(pieceScoreId);
        markDataVo.setPaperItemVoList(paperItemVoList);
        markDataVo.setFinish(task.getFinish());
        markDataVo.setScore(pieceScore.getScore());
        markDataVo.setRejudge(projectSetting.getRejudge());
        markDataVo.setSubjectiveItemScore(pieceScore.getSubjectiveScore());
        markDataVo.setExamClassfication(project.getExamClassfication());
        return markDataVo;
    }

    private void updatePieceScore(PieceScore pieceScore) {
        if (pieceScore.getMarkStartTime() == null) {
            pieceScore.setMarkStartTime(new Date());
            pieceScore.setLastMarkTime(new Date());
            if (!CommonEnums.PIECCE_SCORE_FINSH_1.getCode().equals(pieceScore.getFinish())) {
                pieceScore.setFinish(CommonEnums.PIECCE_SCORE_FINSH_2.getCode());
            }
            pieceScoreMapper.updateById(pieceScore);
        }
    }

    @Override
    public MarkDataVo findTeacherTask(String projectId, String subjectId, String userId) {
        MarkDataVo markDataVo = new MarkDataVo();
        //根据项目id和科目id获取老师未评的考生数据
        PieceScore pieceScore = pieceScoreMapper.getPieceScoreByProjectIdAndSubjectId(projectId, subjectId, userId);
        if (pieceScore != null && StringUtils.isNotEmpty(pieceScore.getId())) {
            markDataVo = this.getStudentPaper(pieceScore.getId(), pieceScore.getEncodeId(), userId, null, CommonEnums.MOBILE_MARK_1.getCode());
        }
        return markDataVo;
    }

    @Override
    public MarkDataVo findTeacherTask(String userId, String projectId, String subjectId, String batchId, String placeId, String roomId) {
        MarkDataVo markDataVo = new MarkDataVo();
        if (StringUtils.isEmpty(batchId)) {
            batchId = "";
        }
        if (StringUtils.isEmpty(placeId)) {
            placeId = "";
        }
        if (StringUtils.isEmpty(roomId)) {
            roomId = "";
        }
        // 根据项目id和科目id获取老师未评的考生数据
        PieceScore pieceScore = pieceScoreMapper.getPieceScoreByBatchIdAndPlaceIdAndRoomId(userId, projectId, subjectId, batchId, placeId, roomId);
        if (pieceScore != null && StringUtils.isNotEmpty(pieceScore.getId())) {
            markDataVo = this.getStudentPaper(pieceScore.getId(), pieceScore.getEncodeId(), userId, null, CommonEnums.MOBILE_MARK_1.getCode());
        }

        // 如果当前科目下没有未评任务，切换下一个科目返回
        // 评卷模式 0：按科目评卷，1：按批次评卷，2：按考场评卷
        if (markDataVo == null || StringUtils.isEmpty(markDataVo.getAdmissionNum())) {
            // 查询评卷类型
            List<ProjectSetting> projectSettings = projectSettingService.lambdaQuery().eq(ProjectSetting::getProjectId, projectId).list();
            String markModel = "";
            if (!CollectionUtils.isEmpty(projectSettings)) {
                markModel = projectSettings.get(0).getMarkModel();
            }

            // 按科目评卷就不用切换了，因为不在一个评卷任务下
            if (MarkmodelEnums.MARK_MODEL_SUBJECT.getCode().equals(markModel)) {
                return markDataVo;
            }

            List<Task> taskList = taskService.lambdaQuery()
                    .eq(Task::getProjectId, projectId)
                    .eq(StringUtils.isNotEmpty(roomId), Task::getRoomId, roomId).list();
            if (CollectionUtils.isEmpty(taskList)) {
                return markDataVo;
            }
            List<String> taskIds = taskList.stream().map(item -> item.getId()).collect(Collectors.toList());
            // 查询未评卷科目
            List<PieceScore> pieceScoreUnMarkList = pieceScoreService.lambdaQuery().in(PieceScore::getTaskId, taskIds).eq(PieceScore::getUserId, userId)
                    .ne(PieceScore::getFinish, CommonEnums.PIECCE_SCORE_FINSH_1.getCode()).list();
            if (CollectionUtils.isNotEmpty(pieceScoreUnMarkList) && pieceScoreUnMarkList.size() > 0) {
                PieceScore next = pieceScoreUnMarkList.get(0);
                markDataVo = this.getStudentPaper(next.getId(), next.getEncodeId(), userId, null, CommonEnums.MOBILE_MARK_1.getCode());
            }
        }

        return markDataVo;
    }

    @Override
    @Transactional
    public Integer submitTeacherTask(MarkDataVo markDataVo, String userId) {
        log.info("保存的评卷内容是:{}", FastJsonUtil.getBeanToJson(markDataVo));
        Task task = taskMapper.selectById(markDataVo.getTaskId());
        if (null == task) {
            throw new MarkException("评卷任务不存在！");
        }
        Project project = projectMapper.selectById(task.getProjectId());
        if (null == project) {
            throw new MarkException("评卷项目不存在！");
        }
        markDataVo.setTask(task);
        // 获取评卷时间设置
        ProjectSetting projectSetting = projectSettingMapper.getProjectSettingByProjectId(task.getProjectId());
        
        // 如果是已经完成评卷但是不允许回评，则直接阻断评卷
        if (RejudgeEnums.MARK_TYPE_UNALLOW_REVIEW.getCode().equals(projectSetting.getRejudge()) && CommonEnums.MARK_STATUS_2.getCode().equals(task.getMarkStatus())) {
            throw new MarkException("该试卷不允许回评！");
        }
        // 评卷时间判断
        getCompareTime(projectSetting, task);

        // 二：获取题目的内容评卷
        List<PaperItemVo> paperItemVos = markDataVo.getPaperItemVoList();

        // -. 把已经打分和评论的数据进行删除
        itemScoreService.deleteStudentScoreByTaskIdAndEncodeIdAndUserId(task.getId(), task.getEncodeId(), userId);
        
        // -. 保存打分数据
        List<ItemScore> itemScores = new ArrayList<>();
        StringBuilder subScore = new StringBuilder();
        getItemScore2(markDataVo, paperItemVos, itemScores, userId, subScore, CommonEnums.ON_SUBMIT_1.getCode());
        itemScoreService.saveBatch(itemScores);

        // -. 更新评卷块得分内容数据和打分次数
        PieceScore pieceScore = pieceScoreService.selectPieceScoreBySubjectIdAndTaskIdAndEncodeIdAndUserId(task.getSubjectId(), task.getPieceId(), task.getId(), task.getEncodeId(), userId);
        // -. 把主观题的分数计算出来设置到pieceScore表中
        pieceScore.setSubjectiveScore(getPieceSubjectiveScore(markDataVo.getPaperItemVoList()));
        pieceScore.setMarkTimes(null == pieceScore.getMarkTimes() ? 1 : pieceScore.getMarkTimes() + 1);
        pieceScore.setObjectiveScore(null == pieceScore.getObjectiveScore() ? BigDecimal.ZERO : pieceScore.getObjectiveScore());
        pieceScore.setScore(pieceScore.getObjectiveScore().add(pieceScore.getSubjectiveScore()));
        pieceScore.setFinish(CommonEnums.PIECCE_SCORE_FINSH_1.getCode());
        pieceScore.setMarkStartTime(null == pieceScore.getMarkStartTime() ? DateUtils.asDate(LocalDateTime.now()) : pieceScore.getMarkStartTime());
        pieceScore.setMarkEndTime(DateUtils.asDate(LocalDateTime.now()));
        // 计算评卷时间
        long markTime = pieceScore.getMarkEndTime().getTime() - pieceScore.getMarkStartTime().getTime();
        pieceScore.setDuration(new BigDecimal(markTime / 1000));
        pieceScore.setLastMarkTime(new Date());
        pieceScoreService.updateById(pieceScore);

        // 存储评分流水记录
        pieceScoreLogService.save(buildPieceScoreLog(pieceScore));

        // -. 对交叉评卷和流水评卷，处理是否评卷完成查看pieseScore是否都为完成,然后把完成情况在task中更新
        if (projectSetting.getMarkType().equals(MarkTypeEnums.MARK_TYPE_CROSS.getCode())) {
            List<PieceScore> list = pieceScoreService.selectPieceScoreByTaskId(task.getId(), null);
            // 是否全部评分
            boolean allFinsh = true;
            // 主观题分数
            BigDecimal allSubjectiveScore = BigDecimal.ZERO;
            for (PieceScore score : list) {
                if (score.getFinish() == null || !score.getFinish().equals(CommonEnums.PIECCE_SCORE_FINSH_1.getCode())) {
                    allFinsh = false;
                    break;
                }
                if (score.getSubjectiveScore() != null) {
                    allSubjectiveScore = allSubjectiveScore.add(score.getSubjectiveScore());
                }
            }
            
            // 如果全部完成评卷
            if (allFinsh) {
                // 如果全部已经评分完，更新task为已完成状态
                task.setMarkStatus(CommonEnums.MARK_STATUS_2.getCode());
                task.setStatus(CommonEnums.MARK_STATUS_2.getCode());
                task.setLoadby(userId);
                taskMapper.updateStatus(task);

                // 更新subjectScore表
                SubjectScore oldSubjectScore = subjectScoreService.getStudentSubjectScore(task.getProjectId(), task.getSubjectId(), task.getEncodeId());
                boolean flag = true; // 更新或插入
                if (oldSubjectScore == null) {
                    flag = false;
                    oldSubjectScore = buildSubjectScore(task);
                }
                // 主观题平均分数
                // 返回小题得分
                List<CandidateSubjectiveScoreVO> candidateSubjectiveScoreVOS = getCandidateSubjectiveScoreVOs(task.getProjectId(), task.getEncodeId());
                log.info("## 小题得分列表candidateSubjectiveScoreVOS: {}", FastJsonUtil.getBeanToJson(candidateSubjectiveScoreVOS));

                // 这里需要特别处理下，如果计算的四舍五入的总分数和小题分数不一致，则取小题的总分数，和其他系统保持一致
                BigDecimal allChildSubjectiveScore = BigDecimal.ZERO;
                if (CollectionUtils.isNotEmpty(candidateSubjectiveScoreVOS)) {
                    for (Iterator<CandidateSubjectiveScoreVO> iterator = candidateSubjectiveScoreVOS.iterator(); iterator.hasNext(); ) {
                        CandidateSubjectiveScoreVO candidateSubjectiveScoreVO = iterator.next();

                        // 只存当前评的这张试卷分，这里试卷不可能为空
                        String paperRealId = paperItemVos.get(0).getPaperId();
                        Paper paper = paperService.getById(paperRealId);
                        if (candidateSubjectiveScoreVO.getPaperId().equals(paper.getPaperId())) {
                            log.info(">>>>>> 只取当前科目");
                            allChildSubjectiveScore = allChildSubjectiveScore.add(candidateSubjectiveScoreVO.getScore());
                        }

                    }
                }
                BigDecimal avgSubjectiveScore = allSubjectiveScore.divide(new BigDecimal(list.size()), 2, BigDecimal.ROUND_HALF_UP);
                // 设置主观题分数
                oldSubjectScore.setSubjectiveScore(avgSubjectiveScore);
                oldSubjectScore.setTotalScore(null != oldSubjectScore.getObjectiveScore() ? avgSubjectiveScore.add(oldSubjectScore.getObjectiveScore()) : avgSubjectiveScore);
                oldSubjectScore.setChildSubjectiveScore(allChildSubjectiveScore);

                log.info("## 科目得分对象SubjectScore：{}", FastJsonUtil.getBeanToJson(oldSubjectScore));
                if (flag) {
                    subjectScoreService.updateById(oldSubjectScore);
                } else {
                    subjectScoreService.save(oldSubjectScore);
                }

                if (CommonEnums.EXAM_CLASSFICATION_2.getCode().equals(project.getExamClassfication())) {
                    // 将评分数据同步到成绩系统
                    Set<String> taskids = new HashSet<>();
                    taskids.add(task.getId());
                    Ayns2Cj ayns2Cj = new Ayns2Cj();
                    ayns2Cj.setSynDataService(synDataService);
                    ayns2Cj.setIApiLogService(iApiLogService);
                    ayns2Cj.setTaskIds(taskids);
                    // 异步形成执行批处理操作，可能数据量比较大
                    ExecutorPoolUtil.getExecutorService().execute(ayns2Cj);
                } else {
                    // 更新考生评卷状态
                    UpdateCandidateJudgeStateVO updateCandidateJudgeStateVO = new UpdateCandidateJudgeStateVO();
                    updateCandidateJudgeStateVO.setProjectId(task.getProjectId());
                    updateCandidateJudgeStateVO.setAdmissionNum(task.getEncodeId());
                    updateCandidateJudgeStateVO.setSubjectiveScore(String.valueOf(avgSubjectiveScore));
                    if (!allChildSubjectiveScore.equals(avgSubjectiveScore)) {
                        updateCandidateJudgeStateVO.setSubjectiveScore(String.valueOf(allChildSubjectiveScore));
                    }

                    //试卷包需要考生考多科目需要科目全部评卷完才推送考务
                    QueryWrapper<Task> taskWrapper = new QueryWrapper<>();
                    taskWrapper.lambda().eq(Task::getProjectId, task.getProjectId()).eq(Task::getEncodeId, task.getEncodeId());
                    List<Task> tasks = taskMapper.selectList(taskWrapper);
                    // 是否全部评分
                    boolean allSubjectFinsh = true;
                    for (Task t : tasks) {
                        //排查本次提交的这条任务
                        if (t.getId().equals(task.getId())) {
                            continue;
                        }
                        //查看之前的任务是否有未完成任务
                        if (!CommonEnums.MARK_STATUS_2.getCode().equals(t.getMarkStatus())) {
                            allSubjectFinsh = false;
                            break;
                        }
                    }
                    if (allSubjectFinsh) {
                        updateCandidateJudgeStateVO.setCandidateSubjectiveScoreList(candidateSubjectiveScoreVOS);
                        log.info("## 非现考现评交叉评卷考中成绩同步params:{}", JSONObject.toJSONString(updateCandidateJudgeStateVO));
                        ApiResponse<?> result = kwClient.updateCandidateJudgeState(updateCandidateJudgeStateVO);
                        log.info("## 非现考现评交叉评卷考中成绩同步result:{}", JSONObject.toJSONString(result));
                    }
                 }
            } else {
                // 更新task为已评卷中状态
                task.setMarkStatus(CommonEnums.MARK_STATUS_1.getCode());
                task.setStatus(CommonEnums.MARK_STATUS_1.getCode());
                task.setLoadby(userId);
                taskMapper.updateStatus(task);
            }
        } else {
            // 更新task为已完成状态
            task.setMarkStatus(CommonEnums.MARK_STATUS_2.getCode());
            task.setStatus(CommonEnums.MARK_STATUS_2.getCode());
            task.setLoadby(userId);
            taskMapper.updateStatus(task);

            // INFO 【这个不知道是不是正确的代码，用了一部分旧的逻辑】 更新subjectScore表
            SubjectScore subjectScore = subjectScoreService.getStudentSubjectScore(task.getProjectId(), task.getSubjectId(), task.getEncodeId());
            boolean flag = true;
            if (subjectScore == null) {
                flag = false;
                subjectScore = buildSubjectScore(task);
            }

            PieceScore subjectPieceScore = pieceScoreService.selectPieceScoreByTaskIdLimitOne(task.getId());
            subjectScore.setSubjectiveScore(subjectPieceScore.getSubjectiveScore());
            subjectScore.setChildSubjectiveScore(subjectPieceScore.getSubjectiveScore());
            BigDecimal totalScore = BigDecimal.ZERO;
            if (null != subjectPieceScore.getSubjectiveScore()) {
                totalScore = totalScore.add(subjectPieceScore.getSubjectiveScore());
            }
            if (null != subjectPieceScore.getObjectiveScore()) {
                totalScore = totalScore.add(subjectPieceScore.getObjectiveScore());
            }
            subjectScore.setTotalScore(totalScore);
            if (flag) {
                subjectScoreService.updateById(subjectScore);
            } else {
                subjectScoreService.save(subjectScore);
            }


            if (CommonEnums.EXAM_CLASSFICATION_2.getCode().equals(project.getExamClassfication()) ) {
                // 现考现评直接推送成绩到成绩系统
                Set<String> taskids = new HashSet<>();
                taskids.add(task.getId());
                Ayns2Cj ayns2Cj = new Ayns2Cj();
                ayns2Cj.setSynDataService(synDataService);
                ayns2Cj.setTaskIds(taskids);
                ayns2Cj.setIApiLogService(iApiLogService);
                // 异步形成执行批处理操作，可能数据量比较大
                ExecutorPoolUtil.getExecutorService().execute(ayns2Cj);

                // 现考现评评完更新考中考生状态
                List<TaskVo> updateKwStatusTasks = new ArrayList<>();
                if (CommonEnums.STUDENT_ABSENT_0.getCode().equals(task.getAbsent())) {
                    updateKwStatusTasks.add(BeanUtil.copyProperties(task, TaskVo.class));
                }
                if (CollectionUtils.isNotEmpty(updateKwStatusTasks)) {
                    batchUpdateStudentStatusKw.setTaskVos(updateKwStatusTasks);
                    batchUpdateStudentStatusKw.setKwClient(kwClient);
                    batchUpdateStudentStatusKw.setKwStatus(CommonEnums.KW_STUDENT_ABSENT_30.getCode());
                    // 异步形成执行批处理操作，可能数据量比较大
                    ExecutorPoolUtil.getExecutorService().execute(batchUpdateStudentStatusKw);
                }
            } else {
                // 更新考生评卷状态
                UpdateCandidateJudgeStateVO updateCandidateJudgeStateVO = new UpdateCandidateJudgeStateVO();
                updateCandidateJudgeStateVO.setProjectId(task.getProjectId());
                updateCandidateJudgeStateVO.setAdmissionNum(task.getEncodeId());
                updateCandidateJudgeStateVO.setSubjectiveScore(pieceScore.getSubjectiveScore().toString());
                // 返回小题得分
                List<CandidateSubjectiveScoreVO> candidateSubjectiveScoreVOS = getCandidateSubjectiveScoreVOs(task.getProjectId(), task.getEncodeId());
                updateCandidateJudgeStateVO.setCandidateSubjectiveScoreList(candidateSubjectiveScoreVOS);
                //试卷包需要考生考多科目需要科目全部评卷完才推送考务
                QueryWrapper<Task> taskWrapper = new QueryWrapper<>();
                taskWrapper.lambda().eq(Task::getProjectId, task.getProjectId()).eq(Task::getEncodeId, task.getEncodeId());
                List<Task> tasks = taskMapper.selectList(taskWrapper);
                // 是否全部评分
                boolean allFinsh = true;
                for (Task t : tasks) {
                    //排查本次提交的这条任务
                    if (t.getId().equals(task.getId())) {
                        continue;
                    }
                    //查看之前的任务是否有未完成任务
                    if (!CommonEnums.MARK_STATUS_2.getCode().equals(t.getMarkStatus())) {
                        allFinsh = false;
                        break;
                    }
                }
                if (allFinsh) {
                    log.info("## 非现考现评流水评卷考中成绩同步params:{}", JSONObject.toJSONString(updateCandidateJudgeStateVO));
                    ApiResponse<?> result = kwClient.updateCandidateJudgeState(updateCandidateJudgeStateVO);
                    log.info("## 非现考现评流水评卷考中成绩同步result:{}", JSONObject.toJSONString(result));
                }
            }
        }
        // 日志
        saveLog(task, pieceScore, subScore.toString(), markDataVo.getPieceScoreId(), userId);
        return ResponseCode.SUCCESS;
    }


    private PieceScoreLog buildPieceScoreLog(PieceScore pieceScore) {
        PieceScoreLog pieceScoreLog = new PieceScoreLog();
        pieceScoreLog.setId(UUIDUtils.newSortUUID());
        pieceScoreLog.setObjectiveScore(pieceScore.getObjectiveScore());
        pieceScoreLog.setPieceScoreId(pieceScore.getId());
        pieceScoreLog.setScore(pieceScore.getScore());
        pieceScoreLog.setSubjectiveScore(pieceScore.getSubjectiveScore());
        pieceScoreLog.setUserId(pieceScore.getUserId());
        return pieceScoreLog;
    }

    /**
     * 判断评卷时间是否在区间
     *
     * @param taskTime
     */
    private void compareTime(TaskTime taskTime) {
        if (null != taskTime) {
            if (null != taskTime.getEndTime() && taskTime.getEndTime().compareTo(new Date()) < 0) {
                throw new MarkException("评卷已经结束，不允许评卷！");
            }
            if (null != taskTime.getStartTime() && taskTime.getStartTime().compareTo(new Date()) > 0) {
                throw new MarkException("评卷还未开始！");
            }
        }
    }

    @Override
    public List<MarkData> getSudentAnswer(String projectId, String subjectId, String pieceCode, String currUserId) {
        return null;
    }

    public void getItemScore(MarkData markData, List<PaperItemVo> paperItemVos, List<ItemScore> itemScores, String userId, StringBuffer subScore) {
        String pieceId = markData.getPieceId();
        Task task = markData.getTask();
        String encodeId = task.getEncodeId();
        String taskId = task.getId();
        for (PaperItemVo paperItemVo : paperItemVos) {
            //只需要主观题和不知道主客观类型的复合题
            if (paperItemVo.getItemViewPoint() == null || !paperItemVo.getItemViewPoint()) {
                ItemScore itemScore = new ItemScore();
                itemScore.setPieceId(pieceId);
                itemScore.setEncodeId(encodeId);
                itemScore.setItemId(paperItemVo.getTopicId());
                BigDecimal realScore = paperItemVo.getRealScore();
                itemScore.setScore(realScore);
                itemScore.setStage(Constants.MARK_STAGE);
                itemScore.setTaskId(taskId);
                itemScore.setUserId(userId);
                itemScore.setItemViewPoint(paperItemVo.getItemViewPoint());
                itemScore.setRemark(paperItemVo.getRemark());
                itemScores.add(itemScore);
                if (paperItemVo.getItemLevel() == 3) {
                    subScore.append(realScore).append(",");
                }
                List<PaperItemVo> children = paperItemVo.getChildren();
                if (children != null && children.size() > 0) {
                    getItemScore(markData, children, itemScores, userId, subScore);
                }
            }
        }
    }

    /**
     * 获取小题的分数itemScore数据
     *
     * @param markDataVo
     * @param paperItemVos
     * @param itemScores
     * @param userId
     * @param subScore
     */
    public void getItemScore2(MarkDataVo markDataVo, List<PaperItemVo> paperItemVos, List<ItemScore> itemScores,
                              String userId, StringBuilder subScore, Integer operation) {
        String pieceId = markDataVo.getTask().getPieceId();
        Task task = markDataVo.getTask();
        String encodeId = task.getEncodeId();
        String taskId = task.getId();

        for (PaperItemVo paperItemVo : paperItemVos) {
            //只需要主观题和不知道主客观类型的复合题
            if (paperItemVo.getItemViewPoint() == null || !paperItemVo.getItemViewPoint()) {
                ItemScore itemScore = new ItemScore();
                itemScore.setId(UUIDUtils.newSortUUID());
                itemScore.setPieceId(pieceId);
                itemScore.setEncodeId(encodeId);
                itemScore.setItemId(paperItemVo.getId());
                BigDecimal realScore = paperItemVo.getObtainScore();
                itemScore.setScore(realScore);
                itemScore.setStage(Constants.MARK_STAGE);
                itemScore.setTaskId(taskId);
                itemScore.setUserId(userId);
                itemScore.setItemViewPoint(paperItemVo.getItemViewPoint());
                itemScore.setRemark(paperItemVo.getRemark());
                if (CommonEnums.ON_SUBMIT_1.getCode().equals(operation)) {
                    itemScore.setFinish(CommonEnums.PIECCE_SCORE_FINSH_1.getCode());
                }
                // 所有的题目里面排除大题，排除复合题, 大题，和 单选题
                if (!("compound".equals(paperItemVo.getItemType()) ||
                        "topic".equals(paperItemVo.getItemType()) ||
                        "single".equals(paperItemVo.getItemType()))) {
                    itemScores.add(itemScore);
                }

                if (paperItemVo.getItemLevel() == 3) {
                    subScore.append(realScore).append(",");
                }
                List<PaperItemVo> children = paperItemVo.getChildren();
                if (CollUtil.isNotEmpty(children)) {
                    getItemScore2(markDataVo, children, itemScores, userId, subScore, operation);
                }
            }
        }
    }


    @Override
    public List<Task> queryTaskList(String projectId) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>();
        queryWrapper.lambda().eq(Task::getProjectId, projectId);
//        queryWrapper.groupBy(getGroupBy(markModel));
        List<Task> tasks = taskMapper.selectList(queryWrapper);
        return tasks;
    }


    @Override
    public List<Task> queryTaskGroupByMarkModel(String projectId) {
        return taskMapper.queryTaskGroupByMarkModel(projectId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveTaskByUser(String projectId, String subjectId, String currUserId, String batchId, String placeId, String roomId) {
        List<PieceScore> pieceScores = pieceScoreMapper.getPieceScoreByUserId(projectId, subjectId, currUserId, batchId, placeId, roomId);
        // 当前用户所以的评卷任务
        Map<String, PieceScore> allPieceScores = new HashMap<>();
        if (CollectionUtils.isEmpty(pieceScores)) {
            return true;
        } else {
            for (PieceScore pieceScore : pieceScores) {
                pieceScore.setFinish(CommonEnums.PIECCE_SCORE_FINSH_1.getCode());
                allPieceScores.put(pieceScore.getEncodeId(), pieceScore);
            }
        }

        // 同步执行,把picescore都设置为已经完成已经给评卷时间赋值
        udpatePieceSocreDate(pieceScores);

        // 判断是否为流水评卷，和交叉评卷
        ProjectSetting projectSetting = projectSettingMapper.getProjectSettingByProjectId(projectId);

        // 如果只是流水评卷直接修改考生task数据状态
        String userId = null;
        if (projectSetting.getMarkType().equals(MarkTypeEnums.MARK_TYPE_FLOW.getCode())) {
            userId = currUserId;
        }
        // 获取已经评卷完成的学生
        List<TaskVo> taskVoList = taskMapper.getFinishTaskVoList(projectId, subjectId, userId, batchId, placeId, roomId);
        // 设置推送的学生task任务
        List<TaskVo> pushTaskVoList = getPushTaskVoList(taskVoList);
        // 所有已经评卷完成的学生的subjectScore设置主观题分数和总分数
        // 更新pushTaskVoList中的任务全部为已完成,并且设置subjectScore表中的得分数据
        if (CollectionUtils.isNotEmpty(pushTaskVoList)) {
            // 那么把该考试下的所有考生task都设置为已经完成
            taskMapper.updateTaskListStatus(pushTaskVoList);
            //未完成的任务
            List<String> unFinishTaskIds = new ArrayList<>();
            Set<String> finishTaskIds = pushTaskVoList.stream().map(t -> t.getId()).collect(Collectors.toSet());
            for (TaskVo taskVo : taskVoList) {
                if (!finishTaskIds.contains(taskVo.getId())) {
                    unFinishTaskIds.add(taskVo.getId());
                }
            }
            if (CollectionUtils.isNotEmpty(unFinishTaskIds)) {
                taskMapper.updateTaskMarkStatusByIds(unFinishTaskIds);
            }
            //存在没有全部完成的，所以需要更新为评卷中
        } else {
            if (CollectionUtils.isNotEmpty(taskVoList)) {
                List<String> finishTaskIds = taskVoList.stream().map(t -> t.getId()).collect(Collectors.toList());
                taskMapper.updateTaskMarkStatusByIds(finishTaskIds);
            }
        }
        // 获取所有的准考证号
        List<String> admissionNums = new ArrayList<>();
        Map<String, TaskVo> notNeedPushTaskVoMap = new HashMap<>();
        for (TaskVo taskVo : taskVoList) {
            if (StringUtils.isNoneEmpty(taskVo.getAdmissionNum())) {
                admissionNums.add(taskVo.getAdmissionNum());
                notNeedPushTaskVoMap.put(taskVo.getAdmissionNum(), taskVo);
            }
        }

        Map<String, TaskVo> needPushTaskVoMap = new HashMap<>();
        for (TaskVo taskVo : pushTaskVoList) {
            if (StringUtils.isNoneEmpty(taskVo.getAdmissionNum())) {
                needPushTaskVoMap.put(taskVo.getAdmissionNum(), taskVo);
            }
        }

        // 找考生所有的需要作答题目
        List<PaperItemVo> paperItemVos = getAllPaperItemByProjectIdAndSubjectId(projectId, subjectId);

        Map<String, PaperItemVo> allItemMap = new HashMap<>();
        for (PaperItemVo paperItemVo : paperItemVos) {
            allItemMap.put(paperItemVo.getId(), paperItemVo);
        }

        List<SubjectScore> updateSubjectScore = new ArrayList<>();
        List<ItemScore> itemScores = new ArrayList<>();
        // 所有考生的准考证号码
        if (CollectionUtils.isNotEmpty(admissionNums)) {
            List<SubjectScore> subjectScores = subjectScoreMapper.getStudentSubjectScores(projectId, subjectId, admissionNums);
            if (!CollectionUtils.isEmpty(subjectScores)) {
                List<String> itemScoreIds = new ArrayList<>();
                for (SubjectScore subjectScore : subjectScores) {
                    if (admissionNums.contains(subjectScore.getEncodeId())) {
                        TaskVo finishTaskVo = needPushTaskVoMap.get(subjectScore.getEncodeId());
                        TaskVo unFinishTaskVo = notNeedPushTaskVoMap.get(subjectScore.getEncodeId());
                        if (null != finishTaskVo) {
                            subjectScore.setTotalScore(finishTaskVo.getScore());
                            subjectScore.setSubjectiveScore(finishTaskVo.getSubjectiveScore());
                            subjectScore.setObjectiveScore(finishTaskVo.getObjectiveScore());
                            subjectScore.setCollectStatus(Integer.valueOf(SubjectScoreStageEnums.SUMMARY.getCode()));
                            // 更新科目汇总分数
//							subjectScoreMapper.updateById(subjectScore);
                            updateSubjectScore.add(subjectScore);
                        }
                        // 计算该考生有哪些题目是未主动评分的
                        List<PaperItemVo> paperItemVosTemp = new ArrayList<>();
                        paperItemVosTemp.addAll(paperItemVos);
                        List<ItemScoreVo> studentItemScores = itemScoreService.getStudentItemScore(projectId, subjectScore.getAdmissionNum(), currUserId);
                        List<String> tempitemScoreIds = studentItemScores.stream().map(e -> e.getItemId()).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(tempitemScoreIds)) {
                            itemScoreIds.addAll(tempitemScoreIds);
                        }
                        for (Iterator<PaperItemVo> iterator = paperItemVosTemp.iterator(); iterator.hasNext(); ) {
                            PaperItemVo paperItemVo = iterator.next();
                            for (ItemScoreVo itemScoreVo : studentItemScores) {
                                if (paperItemVo.getId().equals(itemScoreVo.getItemId())) {
                                    iterator.remove();
                                }
                            }
                        }
                        // 只保存当前用户考生的评分数据
                        PieceScore pieceScore = allPieceScores.get(subjectScore.getEncodeId());
                        if (!CollectionUtils.isEmpty(paperItemVosTemp)) {
//							List<ItemScore> ItemScores = new ArrayList<>();
                            for (PaperItemVo paperItemVo : paperItemVosTemp) {
                                if (null == pieceScore) {
                                    continue;
                                }
                                // 一：保存评分数据
                                ItemScore itemScore = new ItemScore();
                                // 没有主动评分的默认给0分
                                itemScore.setScore(BigDecimal.ZERO);
                                itemScore.setPieceId(pieceScore.getPieceId());
                                itemScore.setItemId(paperItemVo.getId());
                                itemScore.setTaskId(unFinishTaskVo.getId());
                                itemScore.setUserId(currUserId);
                                itemScore.setItemViewPoint(true);
                                itemScore.setEncodeId(unFinishTaskVo.getAdmissionNum());
                                itemScore.setStage(Constants.MARK_STAGE);
                                itemScore.setRemark("");
                                itemScore.setFinish(CommonEnums.PIECCE_SCORE_FINSH_1.getCode());
                                itemScores.add(itemScore);
                            }
                            // 保存该考生所有的未主动评分的题目分数记录
//							itemScoreService.saveBatch(ItemScores);
                        }
                    }
                }
                // 批量更新科目汇总分数
                if (!CollectionUtils.isEmpty(updateSubjectScore)) {
                    subjectScoreService.updateBatchById(updateSubjectScore);
                }
                // 批量保存该考生所有的未主动评分的题目分数记录
                if (!CollectionUtils.isEmpty(itemScores)) {
                    itemScoreService.saveBatch(itemScores);
                }
                // 更新已经评卷题目状为已完成
                if (!CollectionUtils.isEmpty(itemScoreIds)) {
                    itemScoreMapper.updateItemScoreByUserId(itemScoreIds, currUserId);
                }
            }
        }

        // 将评分数据同步到成绩系统
        if (CollectionUtils.isNotEmpty(pushTaskVoList)) {
            Set<String> taskids = pushTaskVoList.stream()
                    .map(TaskVo::getId)
                    .collect(Collectors.toSet());
            Ayns2Cj ayns2Cj = new Ayns2Cj();
            ayns2Cj.setSynDataService(synDataService);
            ayns2Cj.setTaskIds(taskids);
            ayns2Cj.setIApiLogService(iApiLogService);
            // 异步形成执行批处理操作，可能数据量比较大
            ExecutorPoolUtil.getExecutorService().execute(ayns2Cj);
        }

        List<TaskVo> updateKwStatusTasks = new ArrayList<TaskVo>();
        if (CollectionUtils.isNotEmpty(pushTaskVoList)) {
            for (Iterator<TaskVo> iterator2 = pushTaskVoList.iterator(); iterator2.hasNext(); ) {
                TaskVo taskVo = iterator2.next();
                if (CommonEnums.STUDENT_ABSENT_0.getCode().equals(taskVo.getAbsent())) {
                    updateKwStatusTasks.add(taskVo);
                }
            }
        }

        if (CollectionUtils.isNotEmpty(updateKwStatusTasks)) {
            batchUpdateStudentStatusKw.setTaskVos(updateKwStatusTasks);
            batchUpdateStudentStatusKw.setKwClient(kwClient);
            batchUpdateStudentStatusKw.setKwStatus(CommonEnums.KW_STUDENT_ABSENT_30.getCode());
            // 异步形成执行批处理操作，可能数据量比较大
            ExecutorPoolUtil.getExecutorService().execute(batchUpdateStudentStatusKw);
        }
        return true;
    }

    private void udpatePieceSocreDate(List<PieceScore> pieceScores) {
        List<PieceScoreLog> pieceScoreLogs = new ArrayList<>(pieceScores.size());
        for (PieceScore pieceScore : pieceScores) {
            pieceScore.setFinish(CommonEnums.PIECCE_SCORE_FINSH_1.getCode());
            BigDecimal subjectiveScore = new BigDecimal("0");
            BigDecimal objectiveScore = new BigDecimal("0");
            BigDecimal total = new BigDecimal("0");
            if (null != pieceScore.getSubjectiveScore()) {
                subjectiveScore = pieceScore.getSubjectiveScore();
            }
            if (null != pieceScore.getObjectiveScore()) {
                objectiveScore = pieceScore.getObjectiveScore();
            }
            total = total.add(subjectiveScore).add(objectiveScore);
            pieceScore.setScore(total);
            pieceScore.setObjectiveScore(objectiveScore);
            pieceScore.setSubjectiveScore(subjectiveScore);
            pieceScore.setUpdateDate(LocalDateTime.now());
            if (null == pieceScore.getMarkStartTime()) {
                pieceScore.setMarkStartTime(new Date());
            }
            pieceScore.setMarkEndTime(new Date());
            pieceScore.setLastMarkTime(new Date());
            Integer marktimes = pieceScore.getMarkTimes();
            if (null == marktimes) {
                marktimes = Integer.valueOf(1);
            } else {
                marktimes = marktimes + 1;
            }
            pieceScore.setMarkTimes(marktimes);
            if (null == pieceScore.getMarkStartTime()) {
                pieceScore.setMarkStartTime(DateUtils.asDate(LocalDateTime.now()));
            }
            pieceScore.setMarkEndTime(DateUtils.asDate(LocalDateTime.now()));
            long l = pieceScore.getMarkEndTime().getTime() - pieceScore.getMarkStartTime().getTime();
            pieceScore.setDuration(new BigDecimal(l / 1000));
            pieceScore.setLastMarkTime(new Date());
            pieceScoreLogs.add(buildPieceScoreLog(pieceScore));
        }
        pieceScoreService.saveOrUpdateBatch(pieceScores);
        pieceScoreLogService.saveOrUpdateBatch(pieceScoreLogs);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer saveTask(MarkDataVo markDataVo, String userId) {
        log.info("保存的评卷内容是：{}", JSON.toJSON(markDataVo));
        Task task = taskMapper.selectById(markDataVo.getTaskId());
        markDataVo.setTask(task);
        String projectId = task.getProjectId();
        String subjectId = task.getSubjectId();
        String pieceId = task.getPieceId();
        String taskId = task.getId();
        String encodeId = task.getEncodeId();

        QueryWrapper<ProjectSetting> querySetting = new QueryWrapper<ProjectSetting>();
        querySetting.lambda().eq(ProjectSetting::getProjectId, projectId);
        ProjectSetting projectSetting = projectSettingMapper.selectOne(querySetting);

        // 一：判断专家是否可以评卷
        // -. 移动端评卷判断
//        if (markDataVo.getMobileMark() == CommonEnums.MOBILE_MARK_0.getCode() && projectSetting.getMobile().equals(CommonEnums.CLIENT_MARK_0.getCode().toString())) {
//            throw new MarkException("移动端暂时不可评卷！");
//        }

        // -. 评卷回评判断
        if (RejudgeEnums.MARK_TYPE_UNALLOW_REVIEW.getCode().equals(projectSetting.getRejudge()) && task.getMarkStatus() == CommonEnums.MARK_STATUS_2.getCode()) {
            throw new MarkException("该试卷不允许回评！");
        }
        // -. 评卷时间判断
        getCompareTime(projectSetting, task);

        //二：获取题目的内容评卷
        List<PaperItemVo> paperItemVos = markDataVo.getPaperItemVoList();

        // -. 把已经打分和评论的数据进行删除
        List<ItemScore> itemScores = new ArrayList<>();
        StringBuilder subScore = new StringBuilder();
        itemScoreService.deleteStudentScoreByTaskIdAndEncodeIdAndUserId(taskId, encodeId, userId);
        // -. 保存打分数据
        getItemScore2(markDataVo, paperItemVos, itemScores, userId, subScore, CommonEnums.ON_SUBMIT_0.getCode());
        itemScoreService.saveBatch(itemScores);

        // -. 把主观题的分数计算出来设置到pieceScore表中
        BigDecimal pieceSubjectiveScore = getPieceSubjectiveScore(markDataVo.getPaperItemVoList());

        //-. 更新评卷块得分内容数据和打分次数
        PieceScore pieceScore = pieceScoreService.lambdaQuery()
                .eq(PieceScore::getSubjectId, subjectId)
                .eq(PieceScore::getPieceId, pieceId)
                .eq(PieceScore::getTaskId, taskId)
                .eq(PieceScore::getEncodeId, encodeId)
                .eq(PieceScore::getUserId, userId)
                .eq(PieceScore::getDelFlag, false)
                .one();
        pieceScore.setSubjectiveScore(pieceSubjectiveScore);
        //保存一次就设置一次评论
//        if (pieceScore.getMarkTimes() == null) {
//            pieceScore.setMarkTimes(1);
//        } else {
//            pieceScore.setMarkTimes(pieceScore.getMarkTimes() + 1);
//        }
        if (pieceScore.getObjectiveScore() == null) {
            pieceScore.setObjectiveScore(new BigDecimal("0"));
        }
        pieceScore.setScore(pieceScore.getObjectiveScore().add(pieceScore.getSubjectiveScore()));
        if (pieceScore.getFinish() != CommonEnums.PIECCE_SCORE_FINSH_1.getCode()) {
            pieceScore.setFinish(CommonEnums.PIECCE_SCORE_FINSH_2.getCode());
        }


        //LastMarkTime记录了最后一次评卷的时间，如果存在，那么再次评卷时候的时长，就是和现在的时间的时间相加加上有的评卷时长
        if (null == pieceScore.getMarkStartTime()) {
            pieceScore.setMarkStartTime(DateUtils.asDate(LocalDateTime.now()));
        }
        pieceScore.setMarkEndTime(DateUtils.asDate(LocalDateTime.now()));
        long l = pieceScore.getMarkEndTime().getTime() - pieceScore.getMarkStartTime().getTime();
        pieceScore.setDuration(new BigDecimal(l / 1000));

//        long l = new Date().getTime() - pieceScore.getLastMarkTime().getTime();
//        if (pieceScore.getDuration() != null) {
//            pieceScore.setDuration(pieceScore.getDuration().add(new BigDecimal(l / 1000)));
//        } else {
//            pieceScore.setDuration(new BigDecimal(l / 1000));
//        }
        pieceScore.setLastMarkTime(new Date());
        pieceScoreService.updateById(pieceScore);
        //保存需要将任务状态变更成评卷中
        task.setMarkStatus(CommonEnums.TASK_MARK_STATUS_1.getCode());
        taskMapper.updateById(task);
        return ResponseCode.SUCCESS;
    }

    @Override
    public List<MarkSubjectVo> getTaskSubject(String currUserId, String projectId, String batchId, String placeId, String roomId) {
        List<MarkSubjectVo> result = new ArrayList<>();

        List<ProjectSetting> projectSettings = projectSettingMapper.selectList(new LambdaQueryWrapper<ProjectSetting>()
                .eq(ProjectSetting::getProjectId, projectId));
        if (!CollectionUtils.isEmpty(projectSettings)) {
            // 只有按考场评卷才传考场id
            if (!MarkmodelEnums.MARK_MODEL_ROOM.getCode().equals(projectSettings.get(0).getMarkModel())) {
                roomId = "";
            }
        }

        // 获取当前用户需要分配的评卷科目
        List<PieceScore> pieceScoreCurrentUser = pieceScoreMapper.getPieceScoreByUserId(projectId, null, currUserId, null, null, roomId);
        if (CollectionUtils.isEmpty(pieceScoreCurrentUser)) {
            return result;
        }
        List<String> subjectIdList = pieceScoreCurrentUser.stream().map(item -> item.getSubjectId()).distinct().collect(Collectors.toList());

        // 应评和已评
        for (String subjectId : subjectIdList) {
            MarkSubjectVo markSubjectVo = new MarkSubjectVo();
            // 全部和已评
            Integer total = 0;
            Integer finish = 0;
            total = pieceScoreCurrentUser.stream().filter(item -> subjectId.equals(item.getSubjectId())).collect(Collectors.toList()).size();
            finish = pieceScoreCurrentUser.stream().filter(item -> subjectId.equals(item.getSubjectId())
                    && CommonEnums.PIECCE_SCORE_FINSH_1.getCode().equals(item.getFinish())).collect(Collectors.toList()).size();
            // 设置科目名称
            List<Subject> subjectList = subjectService.lambdaQuery().eq(Subject::getProjectId, projectId).eq(Subject::getSubjectId, subjectId).list();
            if (subjectList.size() > 0) {
                markSubjectVo.setSubjectName(subjectList.get(0).getSubjectName());
            }
            markSubjectVo.setTotal(total);
            markSubjectVo.setFinishTotal(finish);
            markSubjectVo.setProjectId(projectId);
            markSubjectVo.setSubjectId(subjectId);
            result.add(markSubjectVo);
        }
        return result;
    }

    @Override
    public List<MarkBatchVo> getTaskBatch(String currUserId, String projectId, String subjectId, String batchId, String placeId, String roomId) {
        if (StringUtils.isEmpty(batchId)) {
            batchId = "";
        }
        if (StringUtils.isEmpty(placeId)) {
            placeId = "";
        }
        if (StringUtils.isEmpty(roomId)) {
            roomId = "";
        }
        //统计数量
//        int total = taskMapper.countBatchAllStatus(currUserId, projectId, subjectId, batchId);
//        int finish = taskMapper.countBatchFinishStatus(currUserId, projectId, subjectId, batchId, CommonEnums.PIECCE_SCORE_FINSH_1.getCode());
        Integer total = taskMapper.countAllStatus(currUserId, projectId, subjectId, batchId, placeId, roomId);
        Integer finish = taskMapper.countAllFinishStatus(currUserId, projectId, subjectId, batchId, placeId, roomId, CommonEnums.PIECCE_SCORE_FINSH_1.getCode());

        List<MarkBatchVo> markBatchVoList = new ArrayList<>();
        //获取批次信息
        QueryWrapper<Task> selectTask = new QueryWrapper<Task>();
        selectTask.lambda().eq(Task::getProjectId, projectId).eq(Task::getSubjectId, subjectId).eq(Task::getBatchId, batchId);
        Task task = taskMapper.selectOne(selectTask);

        MarkBatchVo markBatchVo = new MarkBatchVo();
        markBatchVo.setBatchdId(task.getBatchId());
        markBatchVo.setBatchName(task.getBatchName());
        markBatchVo.setFinishTotal(finish);
        markBatchVo.setTotal(total);
        markBatchVo.setSurplusTotal(total - finish);
        markBatchVoList.add(markBatchVo);
        return markBatchVoList;
    }

    @Override
    public List<MarkStatusVo> getTaskStatus(String currUserId, String projectId, String subjectId, String batchId, String placeId, String roomId) {
        //统计数量
        Integer total = taskMapper.countAllStatus(currUserId, projectId, subjectId, batchId, placeId, roomId);
        Integer finish = taskMapper.countAllFinishStatus(currUserId, projectId, subjectId, batchId, placeId, roomId, CommonEnums.PIECCE_SCORE_FINSH_1.getCode());
        Integer unStart = taskMapper.countAllFinishStatus(currUserId, projectId, subjectId, batchId, placeId, roomId, CommonEnums.PIECCE_SCORE_FINSH_0.getCode());

        List<MarkStatusVo> markStatusVoList = new ArrayList<>();
        MarkStatusVo markStatusVo = new MarkStatusVo();
        markStatusVo.setStatusName("未开始");
        markStatusVo.setStatusVal(CommonEnums.MARK_STATUS_0.getCode());
        markStatusVo.setStatusCount(unStart);
        markStatusVo.setTotal(total);
        markStatusVoList.add(markStatusVo);
        MarkStatusVo markStatusVo2 = new MarkStatusVo();
        markStatusVo2.setStatusName("评卷中");
        markStatusVo2.setStatusVal(CommonEnums.MARK_STATUS_1.getCode());
        markStatusVo2.setStatusCount(total - finish - unStart);
        markStatusVo2.setTotal(total);
        markStatusVoList.add(markStatusVo2);
        MarkStatusVo markStatusVo3 = new MarkStatusVo();
        markStatusVo3.setStatusName("已结束");
        markStatusVo3.setStatusVal(CommonEnums.MARK_STATUS_2.getCode());
        markStatusVo3.setStatusCount(finish);
        markStatusVo3.setTotal(total);
        markStatusVoList.add(markStatusVo3);
        return markStatusVoList;
    }

    @Override
    public List<OptionItemVo> getExpertRoom(String projectId, String palceId) {
        return this.baseMapper.getExpertRoom(projectId, palceId);
    }

    private List<TaskVo> getPushTaskVoList(List<TaskVo> taskVoList) {
        List<TaskVo> pushTaskVoList = new ArrayList<>(taskVoList.size());
        try {
            if (CollectionUtils.isEmpty(taskVoList)) {
                return pushTaskVoList;
            }
            for (TaskVo task : taskVoList) {
                //默认交叉评卷是都评论，如果有一个人没评设置为false不推送
                boolean flag = true;
                BigDecimal subjectiveScore = BigDecimal.ZERO;
                // 不同的评卷对主观题分数汇总
                for (PieceScore pieceScore : task.getPieceScoreList()) {
                    task.setObjectiveScore(pieceScore.getObjectiveScore());
                    if (pieceScore.getSubjectiveScore() != null) {
                        subjectiveScore = subjectiveScore.add(pieceScore.getSubjectiveScore());
                    }
                    if (!CommonEnums.PIECCE_SCORE_FINSH_1.getCode().equals(pieceScore.getFinish())) {
                        flag = false;
                    }
                }
                if (flag) {
                    //
                    BigDecimal pingjunScore = subjectiveScore.divide(new BigDecimal(task.getPieceScoreList().size()), 2, BigDecimal.ROUND_HALF_UP);
                    task.setSubjectiveScore(pingjunScore);
                    if (null != pingjunScore && null != task.getObjectiveScore()) {
                        task.setScore(pingjunScore.add(task.getObjectiveScore()));
                    }
                    if (null != pingjunScore && null == task.getObjectiveScore()) {
                        task.setScore(pingjunScore);
                    }
                    pushTaskVoList.add(task);
                }
            }
        } catch (Exception e) {
            log.error("getPushTaskVoList error", e);
        }
        return pushTaskVoList;
    }

    private void saveLog(Task task, PieceScore pieceScore, String subScore, String pieceScoreId, String userId) {
        Log log = new Log();
        log.setProjectId(task.getProjectId());
        log.setEncodeId(task.getEncodeId());
        log.setScore(pieceScore.getScore());
        log.setStage(Constants.MARK_STAGE);
        log.setSubScore(subScore);
        log.setTaskId(task.getId());
        log.setUserId(userId);
        log.setPieceScoreId(pieceScoreId);
        logService.save(log);
    }

    @Override
    public List<CandidateSubjectiveScoreVO> getCandidateSubjectiveScoreVOs(String projectId, String encodeId) {
        List<CandidateSubjectiveScoreVO> vos = new ArrayList<>();
        List<ItemScoreVo> studentItemScore = itemScoreMapper.getStudentItemScore(projectId, encodeId);
        List<String> items = new ArrayList<String>();
        if (CollectionUtils.isNotEmpty(studentItemScore)) {
            for (ItemScoreVo itemScore : studentItemScore) {
                items.add(itemScore.getItemId());
            }
        } else {
            return vos;
        }
        Map<String, PaperItem> chilePaperItemMap = new HashMap<String, PaperItem>();
        if (CollectionUtils.isNotEmpty(items)) {
            List<PaperItem> paperItem = paperItemService.getBaseMapper().selectBatchIds(items);
            if (CollectionUtils.isNotEmpty(paperItem)) {
                for (Iterator<PaperItem> iterator = paperItem.iterator(); iterator.hasNext(); ) {
                    PaperItem paperItem2 = iterator.next();
                    // 同步考中的时候把大题的分数过滤掉
                    if (!"0".equals(paperItem2.getParentId())) {
                        chilePaperItemMap.put(paperItem2.getId(), paperItem2);
                    }
                }
            }
        }

        for (ItemScoreVo itemScore : studentItemScore) {
            CandidateSubjectiveScoreVO candidateSubjectiveScoreVO = new CandidateSubjectiveScoreVO();
            // 转换成考中的小题号
            String itemId = itemScore.getItemId();
            PaperItem paperItem = chilePaperItemMap.get(itemId);
            if (null == paperItem) {
                continue;
            }
            candidateSubjectiveScoreVO.setItemId(paperItem.getTopicId());
            candidateSubjectiveScoreVO.setPaperId(itemScore.getPaperId());
            candidateSubjectiveScoreVO.setPaperVersion(String.valueOf(itemScore.getPaperVersion()));
            candidateSubjectiveScoreVO.setScore(itemScore.getScore());
            vos.add(candidateSubjectiveScoreVO);
        }

        // 对相同的itemid去重合并
        Map<String, List<CandidateSubjectiveScoreVO>> candidateSubjectiveScoreVOMap = new HashMap<String, List<CandidateSubjectiveScoreVO>>();
        if (CollectionUtils.isNotEmpty(vos)) {
            for (CandidateSubjectiveScoreVO candidateSubjectiveScoreVO : vos) {
                if (candidateSubjectiveScoreVOMap.containsKey(candidateSubjectiveScoreVO.getItemId())) {
                    List<CandidateSubjectiveScoreVO> candidateSubjectiveScoreVOs = candidateSubjectiveScoreVOMap.get(candidateSubjectiveScoreVO.getItemId());
                    candidateSubjectiveScoreVOs.add(candidateSubjectiveScoreVO);
                } else {
                    List<CandidateSubjectiveScoreVO> candidateSubjectiveScoreVOs = new ArrayList<CandidateSubjectiveScoreVO>();
                    candidateSubjectiveScoreVOs.add(candidateSubjectiveScoreVO);
                    candidateSubjectiveScoreVOMap.put(candidateSubjectiveScoreVO.getItemId(), candidateSubjectiveScoreVOs);
                }
            }
        }

        // 对相同的items-scores取平均值
        List<CandidateSubjectiveScoreVO> result = new ArrayList<>();
        if (MapUtils.isNotEmpty(candidateSubjectiveScoreVOMap)) {
            for (String itemid : candidateSubjectiveScoreVOMap.keySet()) {
                List<CandidateSubjectiveScoreVO> candidateSubjectiveScoreVOs = candidateSubjectiveScoreVOMap.get(itemid);
                if (CollectionUtils.isNotEmpty(candidateSubjectiveScoreVOs)) {
                    CandidateSubjectiveScoreVO candidateSubjectiveScoreVO = candidateSubjectiveScoreVOs.get(0);
                    BigDecimal subjectiveScore = BigDecimal.ZERO;
                    for (CandidateSubjectiveScoreVO candidateSubjectiveScoreVO2 : candidateSubjectiveScoreVOs) {
                        if (null != candidateSubjectiveScoreVO2.getScore()) {
                            subjectiveScore = subjectiveScore.add(candidateSubjectiveScoreVO2.getScore());
                        }
                    }
                    BigDecimal pingjunScore = subjectiveScore.divide(new BigDecimal(candidateSubjectiveScoreVOs.size()), 2, BigDecimal.ROUND_HALF_UP);
                    candidateSubjectiveScoreVO.setScore(pingjunScore);
                    result.add(candidateSubjectiveScoreVO);
                }
            }
        }
        return result;
    }

    private SubjectScore buildSubjectScore(Task task) {
        SubjectScore subjectScore = new SubjectScore();
        subjectScore.setProjectId(task.getProjectId());
        subjectScore.setSubjectId(task.getSubjectId());
        subjectScore.setAdmissionNum(task.getEncodeId());
        subjectScore.setEncodeId(task.getEncodeId());
        subjectScore.setObjectiveScore(BigDecimal.ZERO);
        return subjectScore;
    }


    private BigDecimal getPieceSubjectiveScore(List<PaperItemVo> paperItemVoList) {
        BigDecimal pieceSubjectiveScore = BigDecimal.ZERO;
        for (PaperItemVo paperItemVo : paperItemVoList) {
            BigDecimal topicScore = BigDecimal.ZERO;
            List<PaperItemVo> children = paperItemVo.getChildren();
            for (PaperItemVo child : children) {
                //如果是复合题，那么获取复合题下的分数
                if (child.getItemType().equals(PaperItemTypeCode.ITEM_TYPE_COMPOUND_CODE.getCode())) {
                    List<PaperItemVo> childrenList = child.getChildren();
                    for (PaperItemVo c : childrenList) {
                        if (c.getObtainScore() == null) {
                            topicScore = topicScore.add(BigDecimal.ZERO);
                        } else {
                            topicScore = topicScore.add(c.getObtainScore());
                        }
                    }
                } else {
                    //如果是非复合题
                    if (child.getObtainScore() == null) {
                        topicScore = topicScore.add(BigDecimal.ZERO);
                    } else {
                        topicScore = topicScore.add(child.getObtainScore());
                    }
                }
            }
            pieceSubjectiveScore = pieceSubjectiveScore.add(topicScore);
        }
        return pieceSubjectiveScore;
    }


    private void getCompareTime(ProjectSetting projectSetting, Task task) {
        if (AutoFlagEnums.AUTO_FlAG_OPEN.getCode().toString().equals(projectSetting.getMarkTime())) {
            // 按科目按考场
            if (MarkmodelEnums.MARK_MODEL_SUBJECT.getCode().equals(projectSetting.getMarkModel())
                    || MarkmodelEnums.MARK_MODEL_ROOM.getCode().equals(projectSetting.getMarkModel())) {
                QueryWrapper<TaskTime> settingQuery = new QueryWrapper<TaskTime>();
                settingQuery.lambda()
                        .eq(TaskTime::getProjectId, task.getProjectId())
                        .eq(TaskTime::getSubjectId, task.getSubjectId())
                        .eq(TaskTime::getDelFlag, DelFlagEnum.NORMAL.getCode())
                        .eq(StrUtil.isNotEmpty(task.getRoomId()), TaskTime::getRoomId, task.getRoomId())
                        .last("LIMIT 1");
                TaskTime taskTime = taskTimeMapper.selectOne(settingQuery);
                compareTime(taskTime);
            }
            // 按批次
            if (MarkmodelEnums.MARK_MODEL_BATCH.getCode().equals(projectSetting.getMarkModel())) {
                QueryWrapper<TaskTime> settingQuery = new QueryWrapper<TaskTime>();
                settingQuery.lambda()
                        .eq(TaskTime::getBatchId, task.getBatchId())
                        .eq(TaskTime::getSubjectId, task.getSubjectId())
                        .eq(TaskTime::getDelFlag, DelFlagEnum.NORMAL.getCode())
                        .last("LIMIT 1");
                TaskTime taskTime = taskTimeMapper.selectOne(settingQuery);
                compareTime(taskTime);
            }
        }
    }


    private List<PaperItemVo> getAllPaperItemByProjectIdAndSubjectId(String projectId, String subjectId) {
        // 找考生所有的需要作答题目
        String paperId = paperMapper.getPaperIdByProjectIdAndSubject(projectId, subjectId);
        List<PaperItemVo> paperItemVos = paperItemMapper.selectPaperItemVoList(paperId);
        for (Iterator<PaperItemVo> iterator = paperItemVos.iterator(); iterator.hasNext(); ) {
            PaperItemVo paperItemVo = iterator.next();
            // 所有的题目里面排除大题，排除复合题, 大题，和 单选题
            if ("compound".equals(paperItemVo.getItemType()) || "topic".equals(paperItemVo.getItemType()) || "single".equals(paperItemVo.getItemType())) {
                iterator.remove();
            }
        }
        return paperItemVos;
    }


    @Override
    public List<Task> getTaskSubjects(String projectId, String batchId, String roomId) {
        return taskMapper.getTaskSubjects(projectId, batchId, roomId);
    }
}
